#include "DbSqlite.h"
#include <boost/filesystem.hpp>
#include <iostream>

CDbSqlite::CDbSqlite(void)
{
	m_pDb = NULL;
	m_pVM = NULL;
	m_nDbType = 1;
}

CDbSqlite::~CDbSqlite(void)
{
	FreeQueryResult();
	Close();
}

bool CDbSqlite::Open(const char* ip, int port, const char* user, const char* pwd, const char* name)
{
	FreeQueryResult();
	Close();

	std::unique_lock<std::mutex> guard(m_lock);
	m_szDbIp = ip;
	m_szDbUser = user;
	m_szDbPwd = pwd;
	m_szDbName = name;

	boost::filesystem::path dir = boost::filesystem::current_path();
	boost::filesystem::path file = dir / "app.db3";
	int ret = ::sqlite3_open(file.string().c_str(), &m_pDb);
	return (SQLITE_OK == ret);
}

void CDbSqlite::Close(void)
{
	std::unique_lock<std::mutex> guard(m_lock);
	if (m_pDb != NULL)
	{
		::sqlite3_close(m_pDb);
		m_pDb = NULL;
	}
}

bool CDbSqlite::IsTableExist(const char* tbname)
{
	std::unique_lock<std::mutex> guard(m_lock);
	if (NULL == m_pDb)
		return false;

	char sql[1024] = { 0 };
	sprintf(sql, "SELECT COUNT(*), COUNT(*) FROM sqlite_master where type='table' and name='%s'", tbname);

	char** lppszResult = NULL;
	bool ret = false;

	// 不带回调执行sql语句
	int nRow = 0, nColumn = 0;
	if (::sqlite3_get_table(m_pDb, sql, &lppszResult, &nRow, &nColumn, NULL) == SQLITE_OK)
	{
		// lppResult前面第一行数据是字段名称，从nColumn索引开始才是真正的数据
		int nDataIndex = nColumn;
		ret = (::atoi(lppszResult[nDataIndex]) > 0);
	}
	else
	{
		ret = false;
	}
	::sqlite3_free_table(lppszResult);

	return ret;
}

bool CDbSqlite::CreateTable(const char* sql)
{
	std::unique_lock<std::mutex> guard(m_lock);
	return _Exec(sql);
}

bool CDbSqlite::IsProcedureExist(const char* dbname, const char* procname)
{
	return true;
}

bool CDbSqlite::CreateProcedure(const char* sql)
{
	std::unique_lock<std::mutex> guard(m_lock);
	return _Exec(sql);
}

bool CDbSqlite::Exec(const char* sql)
{
	std::unique_lock<std::mutex> guard(m_lock);
	return _Exec(sql);
}

bool CDbSqlite::_Exec(const char* sql)
{
	if (NULL == m_pDb)
		return false;

	// 可带回调执行sql语句
	int ret = ::sqlite3_exec(m_pDb, sql, NULL, NULL, NULL);
	return (SQLITE_OK == ret);
}

const char* CDbSqlite::GetErrorMessage()
{
	return sqlite3_errmsg(m_pDb);
}

uint64_t CDbSqlite::Insert(const char* sql)
{
	std::unique_lock<std::mutex> guard(m_lock);
	unsigned long long ret = 0xffffffff;
	if (_Exec(sql))
	{
		ret = ::sqlite3_last_insert_rowid(m_pDb);
	}
	return ret;
}

bool CDbSqlite::Delete(const char* sql)
{
	std::unique_lock<std::mutex> guard(m_lock);
	return _Exec(sql);
}

bool CDbSqlite::Update(const char* sql)
{
	std::unique_lock<std::mutex> guard(m_lock);
	return _Exec(sql);
}

bool CDbSqlite::Query(const char* sql)
{
	FreeQueryResult();

	std::unique_lock<std::mutex> guard(m_lock);
	if (NULL == m_pDb)
		return false;

	const char* pTail = NULL;
	int ret = ::sqlite3_prepare(m_pDb, sql, -1, &m_pVM, &pTail);
	if (SQLITE_OK == ret)
	{
		m_ullRow = 0;
		m_nCol = ::sqlite3_column_count(m_pVM);
		return true;
	}

	return false;
}

void CDbSqlite::FreeQueryResult(void)
{
	std::unique_lock<std::mutex> guard(m_lock);
	if (m_pVM != NULL)
	{
		::sqlite3_finalize(m_pVM);
		m_pVM = NULL;
	}
	m_ullRow = 0;
	m_nCol = 0;
}

bool CDbSqlite::FetchNextRow(void)
{
	std::unique_lock<std::mutex> guard(m_lock);
	if (m_pVM != NULL)
	{
		int ret = ::sqlite3_step(m_pVM);
		if (SQLITE_DONE == ret)
			return false;
		else if (SQLITE_ROW == ret)
			return true;
	}
	return false;
}

long CDbSqlite::GetRowCount()
{
	return m_ullRow;
}

int CDbSqlite::GetColCount()
{
	return m_nCol;
}

char* CDbSqlite::GetColValue(int nCol)
{
	std::unique_lock<std::mutex> guard(m_lock);
	if (NULL == m_pVM)
		return NULL;

	return (char*)::sqlite3_column_text(m_pVM, nCol);
}
